﻿@using Gurux.DLMS.AMI.Shared
@using Gurux.DLMS.AMI.Shared.DIs
@using Gurux.DLMS.AMI.Shared.DTOs.Agent
@using Gurux.DLMS.AMI.Shared.DTOs.Enums
@using Gurux.DLMS.AMI.Shared.Enums
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using Gurux.DLMS.AMI.Shared.DTOs
@using Gurux.DLMS.AMI.Shared.Rest
@using Microsoft.AspNetCore.SignalR.Client
@using Gurux.DLMS.AMI.Client.Helpers
@using Gurux.DLMS.AMI.Module
@using System.Text.Json;

@namespace Gurux.DLMS.AMI.Client.Pages.Config

@attribute [Authorize(Roles = "Admin, AgentManager")]
@inject NavigationManager NavigationManager
@inject HttpClient Http
@inject IGXNotifier Notifier
@inject ConfirmBase Confirm
@inject IAccessTokenProvider AccessTokenProvider
@implements IDisposable
@implements IGXConfigUpdate

<AuthorizeView Roles=@GXRoles.ToString(GXRoles.Admin, GXRoles.AgentManager)>
    <MenuControl RightCorner="true">
        <ChildContent>
            <MenuItem Text="@Properties.Resources.Remove" Icon="oi oi-trash" OnClick="@OnRemove" />
        </ChildContent>
    </MenuControl>
</AuthorizeView>

@if (_settings != null)
{
    <EditForm Model="@_settings">
        <div class="row">
            <div style="width:100%">
                <div class="form-group">
                    @if (_settings?.Checked != null)
                    {
                        <label>@string.Format(Properties.Resources.LastChecked, ClientHelpers.GetLastChecked(_settings?.Checked))</label>
                    }
                    <button type="button" class="btn btn-link" @onclick="OnCheck">(@Properties.Resources.CheckManually)</button>
                </div>
            </div>
        </div>
    </EditForm>
}

<GXTable @ref="table"
         Context="version" ItemsProvider="@GetItems"
         SelectionMode="SelectionMode.Multiple"
         ShowAllUsers="false"
         OnSearch="@Updated">
    <FilterContent>
        <th>
            <input class="form-control" type="text" placeholder="Filter by version number..."
                   @onchange="@((ChangeEventArgs __e) => filter.Versions[0].Number = Convert.ToString(__e.Value))" />
        </th>
    </FilterContent>
    <MenuContent>
        <ContextMenuItem Text="@Properties.Resources.Remove" Icon="oi oi-trash" OnClick="@OnRemove"></ContextMenuItem>
    </MenuContent>
    <HeaderContent>
        <th>@Properties.Resources.Version</th>
        <th>@Properties.Resources.CreationTime</th>
    </HeaderContent>
    <ItemContent>
        <td>@version.Number</td>
        <td>@version.CreationTime</td>
    </ItemContent>
</GXTable>
<Confirm @ref="DeleteConfirmation"
         ConfirmationChanged="OnDeleteConfirmation"
         AllowDelete="false"
         ConfirmationMessage="@Properties.Resources.AreYouSureYouWantToDeleteSelectedItems">
</Confirm>

@code {

    /// <inheritdoc/>
    public void Update()
    {
        if (!string.IsNullOrEmpty(Parent?.Active?.Settings))
        {
            _settings = JsonSerializer.Deserialize<AgentSettings>(Parent.Active.Settings);
        }
        StateHasChanged();
    }

    /// <summary>
    /// Parent component.
    /// </summary>
    [Parameter]
    public Gurux.DLMS.AMI.Client.Pages.Config.Configurations? Parent { get; set; }

    private string? GetVersion(string? version)
    {
        if (version == null)
        {
            return Properties.Resources.CustomBuild;
        }
        return version;
    }

    private GXAgent filter = new GXAgent(null);
    //Verify that agant can be removed.
    protected ConfirmBase? DeleteConfirmation;
    //Verify that agent can be updated.
    protected ConfirmBase? UpdateConfirmation;
    //Verify that all agent can be updated.
    protected ConfirmBase? UpdatesConfirmation;

    /// <summary>
    /// Table reference.
    /// </summary>
    protected GXTable<GXAgentVersion>? table;

    /// <summary>
    /// Agent settings.
    /// </summary>
    private AgentSettings? _settings;

    private GXAgent? _active;

    /// <summary>
    /// Update table.
    /// </summary>
    protected async Task Updated()
    {
        try
        {
            if (table != null)
            {
                Notifier?.ClearStatus();
                await table.RefreshDataAsync(true);
            }
        }
        catch (Exception ex)
        {
            Notifier?.ProcessError(ex);
        }
    }
    protected override void OnInitialized()
    {
        try
        {
            if (Notifier == null || filter?.Versions == null)
            {
                throw new ArgumentException(Properties.Resources.InvalidNotifier);
            }
            Notifier.On<IEnumerable<GXConfiguration>>(this, nameof(IGXHubEvents.ConfigurationSave), (configurations) =>
           {
               try
               {
                   if (configurations != null)
                   {
                       foreach (var it in configurations)
                       {
                           if (it.Name == GXConfigurations.Agents && !string.IsNullOrEmpty(it.Settings))
                           {
                               _settings = JsonSerializer.Deserialize<AgentSettings>(it.Settings);
                               StateHasChanged();
                               break;
                           }
                       }
                   }
               }
               catch (Exception ex)
               {
                   Notifier?.ProcessError(ex);
               }
           });
            filter.Versions.Add(new GXAgentVersion() { Active = null });
            Notifier.On<IEnumerable<GXAgent>>(this, nameof(IGXHubEvents.AgentUpdate), async (agents) =>
            {
                await Updated();
            });
            Notifier.On<IEnumerable<GXAgent>>(this, nameof(IGXHubEvents.AgentDelete), async (agents) =>
            {
                await Updated();
            });
            Notifier.Clear();
            Notifier.UpdateButtons();
            if (!string.IsNullOrEmpty(Parent?.Active?.Settings))
            {
                _settings = JsonSerializer.Deserialize<AgentSettings>(Parent.Active.Settings);
            }
            else
            {
                _settings = new AgentSettings();
            }
        }
        catch (Exception ex)
        {
            Notifier?.ProcessError(ex);
        }
    }

    private async ValueTask<ItemsProviderResult<GXAgentVersion>> GetItems(GXItemsProviderRequest request)
    {
        //Don't clear status or error is lost.
        Notifier?.ProgressStart();
        try
        {
            if (filter.Versions != null && filter.Versions.Any())
            {
                if (request.Removed)
                {
                    filter.Versions[0].Removed = DateTimeOffset.MaxValue;
                }
                else
                {
                    filter.Versions[0].Removed = null;
                }
            }
            ListAgents req = new ListAgents()
                {
                    Index = request.StartIndex,
                    Count = request.Count,
                    Filter = filter,
                    OrderBy = request.OrderBy,
                    Descending = request.Descending,
                };
            var ret = await Http.PostAsJson<ListAgentsResponse>("api/Agent/Installers", req, request.CancellationToken);
            if (ret.Agents == null || ret.Agents.Length != 1)
            {
                _active = null;
                return default;
            }
            _active = ret.Agents[0];
            if (_active.Versions == null)
            {
                _active = null;
                return default;
            }
            return new ItemsProviderResult<GXAgentVersion>(_active.Versions, _active.Versions.Count);
        }
        catch (TaskCanceledException)
        {
            //Let the table component handle this.
            throw;
        }
        catch (Exception ex)
        {
            Notifier?.ProcessError(ex);
        }
        finally
        {
            Notifier?.ProgressEnd();
        }
        return default;
    }

    /// <summary>
    /// Delete selected agent.
    /// </summary>
    public void OnRemove()
    {
        try
        {
            if (table == null || !table.SingleOrDefault().Any())
            {
                throw new Exception(Gurux.DLMS.AMI.Client.Properties.Resources.NoItemIsSelected);
            }
            DeleteConfirmation?.Show(table?.SingleOrDefault()?.Select(s => Properties.Resources.Version + " " + s.Number).ToArray());
        }
        catch (Exception ex)
        {
            Notifier?.ProcessError(ex);
        }
    }

    /// <summary>
    /// Remove the agent.
    /// </summary>
    public async Task OnDeleteConfirmation(ConfirmArgs args)
    {
        try
        {
            if (args.Confirm && table != null && _active != null && _active.Versions != null)
            {
                foreach (var it in table.SingleOrDefault())
                {
                    _active.Versions.Remove(it);
                }
                UpdateAgent req = new UpdateAgent()
                    {
                        Agents = new GXAgent[] { _active }
                    };
                await Http.PostAsJson<RemoveAgentResponse>("api/Agent/Update", req);
            }
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
        catch (Exception ex)
        {
            Notifier?.ProcessError(ex);
        }
    }

    /// <summary>
    /// Check agent versions manually.
    /// </summary>
    public async void OnCheck()
    {
        Notifier?.ProgressStart();
        Notifier?.ClearStatus();
        try
        {
            CheckManufacturer req = new CheckManufacturer();
            await Http.PostAsJson<CheckManufacturerResponse>("api/Agent/Check", req);
        }
        catch (Exception ex)
        {
            Notifier?.ProcessError(ex);
        }
        finally
        {
            Notifier?.ProgressEnd();
        }
    }

    public void Dispose()
    {
        Notifier.RemoveListener(this);
    }
}
